import logging
import os
import time
import allure
from selenium.common import TimeoutException
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait

class Keywords:
    def __init__(self,driver):
        self.driver=driver

    def find(self,step):
        wait=WebDriverWait(self.driver,10)
        locator=(step["by"],step["value"])
        try:
            if step["index"] is None:
                return wait.until(expected_conditions.presence_of_element_located(locator))
            else:
                return wait.until(expected_conditions.presence_of_all_elements_located(locator))[step["index"]]
        except TimeoutException as e:
            logging.info(f"❌元素不存在--元素位置（{step['by']},{step['value']}）")
    def open(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.get(step["data"])
    def click(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.find(step).click()
    def input(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.find(step).send_keys(step["data"])
    def clear(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.find(step).clear()
    def wait(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            time.sleep(step["data"])

    def screenshot(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            now_time=time.strftime("%Y-%m-%d %H:%M:%S")
            png=self.driver.get_screenshot_as_png()
            allure.attach(png,f"第{step['step_num']}步_{now_time}.png",allure.attachment_type.PNG)

    def refresh(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.refresh()
    def forward(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.forward()
    def back(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.back()
    def switch_to_window(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            handles=self.driver.window_handles
            self.driver.switch_to.window(handles[step["data"]])

    def alert_accept(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.switch_to.alert.accept()
    def alert_dismiss(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.switch_to.alert.dismiss()

    def execute_script_js(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.execute_script(step['data'])

    def double_click(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            action=ActionChains(self.driver)
            action.double_click(self.find(step)).perform()
    def right_click(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            action=ActionChains(self.driver)
            action.context_click(self.find(step)).perform()
    def move_to_element(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            action=ActionChains(self.driver)
            action.move_to_element(self.find(step)).perform()
    def drag_and_drop(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            action=ActionChains(self.driver)
            source=self.find(step)
            target_dict=eval(step["data"])
            target=self.driver.find_element(target_dict["by"],target_dict["value"])
            action.drag_and_drop(source,target).perform()
    def enter(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.find(step).send_keys(Keys.ENTER)

    def upload(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            absolute_path=os.path.abspath(step["data"])
            self.find(step).send_keys(absolute_path)

    def switch_to_frame(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.switch_to.frame(self.find(step))
    def switch_to_default_content(self,step):
        with allure.step(f"第{step['step_num']}步：{step['step_name']}"):
            logging.info(f"第{step['step_num']}步：{step['step_name']}--元素位置（{step['by']},{step['value']}）--数据{step['data']}--组元素索引{step['index']}")
            self.driver.switch_to.default_content()





